package com.syscom.server.qc.ui;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Hashtable;

import com.syscom.safe.wac.buf.SacInputBuffer;
import com.syscom.safe.wac.buf.SacOutputBuffer;
import com.syscom.safe.wac.exception.WacException;
import com.syscom.safe.wac.txbean.TxContext;
import com.syscom.sar.server.constant.QDCActFuncConstant;
import com.syscom.sar.server.rsk.vo.OdrInfo;
import com.syscom.sar.server.rsk.vo.SarCODT;
import com.syscom.sar.server.rsk.vo.SarNBST;
import com.syscom.server.qc.cacheManager.QCManager;
import com.syscom.shared.server.action.Action;
import com.syscom.shared.vo.ResponseStatus;

/**
 * RM -> QC
 * 
 * @author Jean
 */
public class QCAction extends Action {

	@Override
	public void executeAsyncRequest(TxContext ctx, SacInputBuffer req) throws WacException, SQLException, IOException {}

	@Override
	public byte[] executeSyncRequest(TxContext ctx, SacInputBuffer req) throws WacException, SQLException, IOException {
		String sFuncCd = req.readShortString();
		
		if 		(QDCActFuncConstant.QC_FUNC_SEND_QC_TO_ACCU_GENER.equals(sFuncCd)) { return sendQCToAccuForGeneral(ctx, req); }
		else if (QDCActFuncConstant.QC_FUNC_SEND_QC_TO_ACCU_CODT.equals(sFuncCd))  { return sendQCToAccuForCODT(ctx, req); }
		else if (QDCActFuncConstant.QC_FUNC_SEND_QC_TO_ACCU_NBST.equals(sFuncCd))  { return sendQCToAccuForNBST(ctx, req); }
		else if (QDCActFuncConstant.QC_FUNC_SEND_QC_TO_ACCU_MTH.equals(sFuncCd))   { return sendQCToAccuForMth(ctx, req); }
		else if (QDCActFuncConstant.QC_FUNC_SEND_QC_TO_BACK_GENER.equals(sFuncCd)) { return sendQCToBackForGeneral(ctx, req); }
		
		return null;
	}
	
	private byte[] sendQCToAccuForGeneral(TxContext ctx, SacInputBuffer inBuffer) throws WacException, IOException {
		SacOutputBuffer outBuffer = new SacOutputBuffer();
		byte[] bResult = null;
		
		try {
			Hashtable<Integer, double[]> tblNeedToAccu = new Hashtable<Integer, double[]> ();
			
			// OdrInfo
			OdrInfo odrInfo = new OdrInfo();
			odrInfo.parseInBuffer(inBuffer);

			// tblNeedToAccu - Size
			int iTblNeedToAccuLen = inBuffer.readInt();
			
			for(int i = 0 ; i < iTblNeedToAccuLen; i++) {
				// tblNeedToAccu - Key
				int iRuleId = inBuffer.readInt();
				
				// tblNeedToAccu - ValuesLength
				int iValuesLen = inBuffer.readInt();
				
				double[] dValues = new double[iValuesLen];
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblNeedToAccu - Value
					dValues[j] = inBuffer.readDouble();
				}
				
				tblNeedToAccu.put(iRuleId, dValues);
			}
			
			Hashtable<Integer, double[]> tblQC = QCManager.getInstance().receveGeneral(odrInfo, tblNeedToAccu);
			
			outBuffer.writeByte(ResponseStatus.OK);
			
			// tblQC - Size
			int iTblQCLen = tblQC.size();
			outBuffer.writeInt(iTblQCLen);
			
			Integer[] iKeys = new Integer[tblQC.size()];
			tblQC.keySet().toArray(iKeys);
			for (int i = 0 ; i < iTblQCLen; i++) {
				// tblQC - Key
				int iRuleId = iKeys[i];
				outBuffer.writeInt(iRuleId);

				// tblQC - ValuesLength
				double[] dValues = tblQC.get(iRuleId);
				int iValuesLen = dValues.length;
				outBuffer.writeInt(iValuesLen);
				
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblQC - Value
					double dValue = dValues[j];
					outBuffer.writeDouble(dValue);
				}
			}
			bResult = outBuffer.getByteArray();
		}
		finally {
			outBuffer.close();
		}
		
		return bResult;
	}

	private byte[] sendQCToAccuForCODT(TxContext ctx, SacInputBuffer inBuffer) throws WacException, IOException {
		SacOutputBuffer outBuffer = new SacOutputBuffer();
		byte[] bResult = null;
		try {
			Hashtable<Integer, double[]> tblNeedToAccu = new Hashtable<Integer, double[]> ();
			
			// SarCODT
			SarCODT codtVo = new SarCODT();
			codtVo.parseInBuffer(inBuffer);

			// tblNeedToAccu - Size
			int iTblNeedToAccuLen = inBuffer.readInt();
			
			for(int i = 0 ; i < iTblNeedToAccuLen; i++) {
				// tblNeedToAccu - Key
				int iRuleId = inBuffer.readInt();
				
				// tblNeedToAccu - ValuesLength
				int iValuesLen = inBuffer.readInt();
				
				double[] dValues = new double[iValuesLen];
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblNeedToAccu - Value
					dValues[j] = inBuffer.readDouble();
				}
				
				tblNeedToAccu.put(iRuleId, dValues);
			}
			
			Hashtable<Integer, double[]> tblQC = QCManager.getInstance().receveCODT(codtVo, tblNeedToAccu);
			
			outBuffer.writeByte(ResponseStatus.OK);
			
			// tblQC - Size
			int iTblQCLen = tblQC.size();
			outBuffer.writeInt(iTblQCLen);
			
			Integer[] iKeys = new Integer[tblQC.size()];
			tblQC.keySet().toArray(iKeys);
			for (int i = 0 ; i < iTblQCLen; i++) {
				// tblQC - Key
				int iRuleId = iKeys[i];
				outBuffer.writeInt(iRuleId);

				// tblQC - ValuesLength
				double[] dValues = tblQC.get(iRuleId);
				int iValuesLen = dValues.length;
				outBuffer.writeInt(iValuesLen);
				
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblQC - Value
					double dValue = dValues[j];
					outBuffer.writeDouble(dValue);
				}
			}
			bResult = outBuffer.getByteArray();
		}
		finally {
			outBuffer.close();
		}
		
		return bResult;
	}

	private byte[] sendQCToAccuForNBST(TxContext ctx, SacInputBuffer inBuffer) throws WacException, IOException {
		SacOutputBuffer outBuffer = new SacOutputBuffer();
		byte[] bResult = null;
		try {
			Hashtable<Integer, double[]> tblNeedToAccu = new Hashtable<Integer, double[]> ();
			
			// SarNBST
			SarNBST nbstVo = new SarNBST();
			nbstVo.parseInBuffer(inBuffer);

			// tblNeedToAccu - Size
			int iTblNeedToAccuLen = inBuffer.readInt();
			
			for(int i = 0 ; i < iTblNeedToAccuLen; i++) {
				// tblNeedToAccu - Key
				int iRuleId = inBuffer.readInt();
				
				// tblNeedToAccu - ValuesLength
				int iValuesLen = inBuffer.readInt();
				
				double[] dValues = new double[iValuesLen];
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblNeedToAccu - Value
					dValues[j] = inBuffer.readDouble();
				}
				
				tblNeedToAccu.put(iRuleId, dValues);
			}
			
			Hashtable<Integer, double[]> tblQC = QCManager.getInstance().receveNBST(nbstVo, tblNeedToAccu);
			
			outBuffer.writeByte(ResponseStatus.OK);
			
			// tblQC - Size
			int iTblQCLen = tblQC.size();
			outBuffer.writeInt(iTblQCLen);
			
			Integer[] iKeys = new Integer[tblQC.size()];
			tblQC.keySet().toArray(iKeys);
			for (int i = 0 ; i < iTblQCLen; i++) {
				// tblQC - Key
				int iRuleId = iKeys[i];
				outBuffer.writeInt(iRuleId);

				// tblQC - ValuesLength
				double[] dValues = tblQC.get(iRuleId);
				int iValuesLen = dValues.length;
				outBuffer.writeInt(iValuesLen);
				
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblQC - Value
					double dValue = dValues[j];
					outBuffer.writeDouble(dValue);
				}
			}
			bResult = outBuffer.getByteArray();
		}
		finally {
			outBuffer.close();
		}
		
		return bResult;
	}
	
	// Match
	private byte[] sendQCToAccuForMth(TxContext ctx, SacInputBuffer inBuffer) throws WacException, IOException {
		SacOutputBuffer outBuffer = new SacOutputBuffer();
	    byte[] bResult = null;
	    
	    try {
	    	String sProdId = inBuffer.readShortString();
			int iOdrTp = inBuffer.readInt();
			long lShares = inBuffer.readLong();
			double dPrice = inBuffer.readDouble();
			
			QCManager.getInstance().receveMth(sProdId, iOdrTp, lShares, dPrice);
			
			outBuffer.writeByte(ResponseStatus.OK);
	        bResult = outBuffer.getByteArray();
	    }
	    finally {
	    	outBuffer.close();
	    }
        
		return bResult;
	}

	private byte[] sendQCToBackForGeneral(TxContext ctx, SacInputBuffer inBuffer) throws WacException, IOException {
		Hashtable<Integer, double[]> tblNeedToAccu = new Hashtable<Integer, double[]> ();
		
		SacOutputBuffer outBuffer = new SacOutputBuffer();
	    byte[] bResult = null;
	    
	    try {
			// OdrInfo
			OdrInfo odrInfo = new OdrInfo();
			odrInfo.parseInBuffer(inBuffer);

			// tblNeedToAccu - Size
			int iTblNeedToAccuLen = inBuffer.readInt();
			
			for(int i = 0 ; i < iTblNeedToAccuLen; i++) {
				// tblNeedToAccu - Key
				int iRuleId = inBuffer.readInt();
				
				// tblNeedToAccu - ValuesLength
				int iValuesLen = inBuffer.readInt();
				
				double[] dValues = new double[iValuesLen];
				for(int j = 0 ; j < iValuesLen; j++) {
					// tblNeedToAccu - Value
					dValues[j] = inBuffer.readDouble();
				}
				
				tblNeedToAccu.put(iRuleId, dValues);
			}
			
			QCManager.getInstance().receveRollbackGeneral(odrInfo, tblNeedToAccu);
			
			outBuffer.writeByte(ResponseStatus.OK);
	        bResult = outBuffer.getByteArray();
	    }
	    finally {
	    	outBuffer.close();
	    }
	    
	    return bResult;
	}
	
}
